﻿function BangoLogger() {
	var _logEvents = BangoConstants.SETTING_LOGEVENTS();
	var _useOfflineStorage = BangoConstants.SETTING_USEOFFLINESTORAGE();
	var _sessionResumePeriod = BangoConstants.SETTING_SESSION_RESUME_PERIOD();
	var _maximumEventsPerProfile = BangoConstants.SETTING_MAXIMUM_EVENTS_PER_PROFILE();
	var _postOnMaximumEvents = BangoConstants.POST_ON_MAXIMUM_EVENTS_PER_PROFILE();
	var _applicationVersion = "";
	var _applicationType = "";
	var _applicationChannel = "";
	var _userId = "";
	var _bangoUserId = "";
	var _postURL = BangoConstants.SETTING_POST_URL();
	var _findLocation = BangoConstants.SETTING_LOCATION_FIND();
	var _userAgent = "";
	var _product = "";
	var _identifyBangoUser = BangoConstants.SETTING_IDENTIFY_BANGO_USER();
	var _locationSource = BangoConstants.LOCATION_GPS();

	var _deviceBrand = "";
	var _deviceMake = "";
	var _deviceModel = "";
	var _deviceVersion = "";

	var _operatingSystem = "";
	var _operatingSystemVersion = "";

	var _connectionType = BangoConstants.UNKNOWN_CONNECTION();
	var _operatorConnectionType = BangoConstants.UNKNOWN_CONNECTION();
	var connectionTypesSet = false;

	var _applicationId;
	var _isPosting = false;
	var _ajaxPost = null;
	var _ajaxGet = null;
	var _profileForPost = null;
	var _postProfilesCount = 0;
	var _hold = false;

	var _profileLogged = false;

	var _userIdKeyName = "BangoStore_UserId";
	var _bangoUserIdKeyName = "BangoStore_BangoUserId";

	var _networkMode = -1;

	var _operatorCode = "";
	var _operatorSim = "";
	var _operatorName = "";
	var _countryISO = "";

	var _isRoaming = false;

	var _latitude = 0;
	var _longitude = 0;
	var _altitude = 0;
	var _accuracy = 0;

	var networkTransaction = null;
	var connectionStatusTransaction = null;

	this.logEvents = function (logEvents) {
		if (logEvents === undefined) {
			return _logEvents;
		}
		else {
			_logEvents = logEvents;
		}
	};

	this.useOfflineStorage = function (useOfflineStorage) {
		if (useOfflineStorage === undefined) {
			return _useOfflineStorage;
		}
		else {
			_useOfflineStorage = useOfflineStorage;
		}
	};

	this.sessionResumePeriod = function (sessionResumePeriod) {
		if (sessionResumePeriod === undefined) {
			return _sessionResumePeriod;
		}
		else {
			_sessionResumePeriod = sessionResumePeriod;
		}
	};
	this.maximumEventsPerProfile = function (maximumEventsPerProfile) {

		if (maximumEventsPerProfile == undefined) {
			return _maximumEventsPerProfile;
		}
		else {
			_maximumEventsPerProfile = maximumEventsPerProfile;
		}
	};

	this.identifyBangoUser = function(identifyBangoUser) {
		if (identifyBangoUser == undefined) {
			return _identifyBangoUser;
		} else {
			_identifyBangoUser = identifyBangoUser;
		}
	};
	this.postOnMaximumEvents = function (postOnMaximumEvents) {

		if (postOnMaximumEvents == undefined) {
			return _postOnMaximumEvents;
		}
		else {
			_postOnMaximumEvents = postOnMaximumEvents;
		}
	};
	this.latitude = function (latitude) {
		if (latitude == undefined) {
			return _latitude;
		}
		else {
			_latitude = latitude;
		}
	};
	this.longitude = function (longitude) {
		if (longitude == undefined) {
			return _longitude;
		}
		else {
			_longitude = longitude;
		}
	};

	this.altitude = function (altitude) {
		if (altitude == undefined) {
			return _altitude;
		}
		else {
			_altitude = altitude;
		}
	};

	this.accuracy = function (accuracy) {
		if (accuracy == undefined) {
			return _accuracy;
		}
		else {
			_accuracy = accuracy;
		}
	};

	this.applicationVersion = function (applicationVersion) {
		if (applicationVersion === undefined) {
			return _applicationVersion;
		}
		else {
			_applicationVersion = applicationVersion;
		}
	};

	this.applicationType = function (applicationType) {
		if (applicationType === undefined) {
			return _applicationType;
		}
		else {
			_applicationType = applicationType;
		}
	};

	this.applicationChannel = function (applicationChannel) {
		if (applicationChannel === undefined) {
			return _applicationChannel;
		}
		else {
			_applicationChannel = applicationChannel;
		}
	};

	this.userId = function (userId) {
		if (userId === undefined) {
			return _userId;
		}
		else {
			_userId = userId;
		}
	};

	this.bangoUserId = function (bangoUserId) {
		if (bangoUserId === undefined) {
			return _bangoUserId;
		} else {
			_bangoUserId = bangoUserId;
		}
	};

	this.userAgent = function (userAgent) {
		if (userAgent === undefined) {
			return _userAgent;
		}
		else {
			_userAgent = userAgent;
		}
	};

	this.postURL = function (postURL) {
		if (postURL === undefined) {
			return _postURL;
		}
		else {
			_postURL = postURL;
		}
	};

	this.findLocation = function (findLocation) {
		if (findLocation === undefined) {
			return _findLocation;
		}
		else {
			_findLocation = findLocation;
		}
	};

	this.locationSource = function (locationSource) {
		if (locationSource === undefined) {
			return _locationSource;
		}
		else {
			_locationSource = locationSource;
		}
	};

	this.deviceBrand = function (deviceBrand) {
		if (deviceBrand === undefined) {
			return _deviceBrand;
		}
		else {
			_deviceBrand = deviceBrand;
		}
	};

	this.deviceMake = function (deviceMake) {
		if (deviceMake === undefined) {
			return _deviceMake;
		}
		else {
			_deviceMake = deviceMake;
		}
	};

	this.deviceModel = function (deviceModel) {
		if (deviceModel === undefined) {
			return _deviceModel;
		}
		else {
			_deviceModel = deviceModel;
		}
	};

	this.deviceVersion = function (deviceVersion) {
		if (deviceVersion === undefined) {
			return _deviceVersion;
		}
		else {
			_deviceVersion = deviceVersion;
		}
	};

	this.operatingSystem = function (operatingSystem) {
		if (operatingSystem === undefined) {
			return _operatingSystem;
		}
		else {
			_operatingSystem = operatingSystem;
		}
	};

	this.operatingSystemVersion = function (operatingSystemVersion) {
		if (operatingSystemVersion === undefined) {
			return _operatingSystemVersion;
		}
		else {
			_operatingSystemVersion = operatingSystemVersion;
		}
	};

	this.operatorCode = function (operatorCode) {
		if (operatorCode === undefined) {
			return _operatorCode;
		}
		else {
			_operatorCode = operatorCode;
		}
	};

	this.operatorSim = function (operatorSim) {
		if (operatorSim === undefined) {
			return _operatorSim;
		}
		else {
			_operatorSim = operatorSim;
		}
	};

	this.operatorName = function (operatorName) {
		if (operatorName === undefined) {
			return _operatorName;
		}
		else {
			_operatorName = operatorName;
		}
	};

	this.countryISO = function (countryISO) {
		if (countryISO === undefined) {
			return _countryISO;
		}
		else {
			if (countryISO.length == 2 || countryISO.length == 3) {
				_countryISO = countryISO;
			}
		}
	};

	this.isRoaming = function (isRoaming) {
		if (isRoaming === undefined) {
			return _isRoaming;
		}
		else {
			// isRoaming is set to false by default, so it only needs to be updated if it is true
			if (isRoaming === true) {
				_isRoaming = isRoaming;
			}
		}
	};

	this.connectionType = function (connectionType) {
		if (connectionType === undefined) {
			return _connectionType;
		}
		else {
			// Only set it if it is valid, if not it will default to 'OTHER'
			if (connectionType === BangoConstants.WIFI_CONNECTION() || connectionType === BangoConstants.OPERATOR_CONNECTION()) {
				_connectionType = connectionType;
			}
		}
	};

	this.operatorConnectionType = function (operatorConnectionType) {
		if (operatorConnectionType === undefined) {
			return _operatorConnectionType;
		}
		else {
			_operatorConnectionType = operatorConnectionType;
		}
	};

	function setUserId() {
		var userIdString;
		var result;

		if (_userId == "" || _userId == undefined || _userId == null) {
			if (_useOfflineStorage) {
				try {
					if (localStorage.getItem(_userIdKeyName)) {
						userIdString = localStorage.getItem(_userIdKeyName);
					}
				}
				catch (ex) {
					userIdString = null;
				}
			}

			if (userIdString == "" || userIdString == undefined || userIdString == null) {
				// Use milliseconds since epoch as UserId - unlikely that two people will generate one in the same millisecond, can always be changed to GUID's if needed.
				var dt = new Date();
				dt = dt.getTime();
				var useragent = navigator.userAgent;

				//console.log("String to hash for UserID: " + useragent + dt);
				userIdString = calcMD5(useragent + dt + Math.random());

				localStorage.setItem(_userIdKeyName, userIdString);
			}

			_userId = userIdString;
		}

		if (_useOfflineStorage) {
			try {
				//Set userId to localStorage
				localStorage.setItem(_userIdKeyName, _userId);
			}
			catch (ex) {
				//console.log(ex.message + ":" + ex.line);
			}
		}

	};

	function onReadyStateChangeGet() {
		var result;
		var bangoUserIdString;
		try {
			if (_ajaxGet.readyState == 4) {
				result = _ajaxGet.responseXML;
				if (result) {
					var responseCode = result.getElementsByTagName("responseCode");
					var responseCodeText = responseCode[0].textContent;
					if (responseCodeText.indexOf(BangoConstants.POST_RESPONSE_SUCCESS()) > 0) {
						var userIdNode = result.getElementsByTagName("userId");
						bangoUserIdString = userIdNode[0].textContent.substr(0, userIdNode[0].textContent.length - 1);
						bangoUserIdString = bangoUserIdString.substr(1);
						_bangoUserId = bangoUserIdString;
						if (_useOfflineStorage) {
							BangoStorage.LogProfilePersistent(_useOfflineStorage, _bangoUserId);
						}
					}
				}
				else {
					_bangoUserId = null;
				}
			}
		} catch (ex) {

		}
	};
	this.GetBangoUserId = function (bangoNumber) {
		if (!_identifyBangoUser) {
			return;
		}
		var bangoUserId = null;
			var profilePersistent;
			if (_useOfflineStorage) {
				profilePersistent = BangoStorage.GetProfilePersistent(_useOfflineStorage);
				if (profilePersistent.length > 0) {
					bangoUserId = profilePersistent[0].BangoUserId;
					_bangoUserId = bangoUserId;
			} else {
					if (navigator.onLine) {
						if (_identifyBangoUser) {
							if (window.XDomainRequest) {
								_ajaxGet = new XDomainRequest();
							} else if (window.XMLHttpRequest) {
								_ajaxGet = new XMLHttpRequest();
							} else if (window.ActiveXObject) {
								_ajaxGet = new ActiveXObject("Microsoft.XMLHTTP");
							}

							if (_ajaxGet) {
								_ajaxGet.onreadystatechange = onReadyStateChangeGet;
								_ajaxGet.open("GET", BangoConstants.SETTING_IDENTIFIER_URL() + bangoNumber, true);
								_ajaxGet.responseType = "Document";
								_ajaxGet.send(null);
							}
						}
					}
				}
			}
	};

	this.postEventsNow = function (postCurrentProfile, sendAsync) {
		try {
			if (!_isPosting) {
				_isPosting = true;
				if (BangoStorage.bangoStore() != null) {
					for (var profileCounter = 0; profileCounter < BangoStorage.bangoStore().length; profileCounter++) {
						if (postCurrentProfile || BangoStorage.bangoStore()[profileCounter].profileId != BangoStorage.profileId()) {
							var profileForPost = BangoStorage.bangoStore()[profileCounter];
							var eventsToBePosted = [];

							var unpostedEvents = 0;

							for (var i = 0; i < profileForPost.Events.length; i++) {
								if (!profileForPost.Events[i].EventPosted) {
									unpostedEvents += 1;

									if (!profileForPost.Events[i].EventIsPosting) {
										profileForPost.Events[i].EventIsPosting = true;
										eventsToBePosted.push(profileForPost.Events[i]);
									}
								}
							}
							if (eventsToBePosted.length > 0) {
								if (!_isRoaming || isWifi()) {
									profileForPost.Events = eventsToBePosted;
									var poster = new BangoPoster(profileForPost, this.postURL(), this.userAgent(), sendAsync, this.useOfflineStorage());
									poster.postEventsForProfile();
								}
							}
							else if (unpostedEvents == 0) {
								BangoStorage.deleteEventsPosted(_useOfflineStorage, BangoStorage.bangoStore()[profileCounter].profileId);
							}
						}
					}
				}
			}
		}
		catch (ex) {
			console.log(ex.message + ":" + ex.line);
		}
		finally {
			_isPosting = false;
		}

	};

	this.initLogger = function (applicationId) {
		try {
			_applicationId = applicationId;
			this.GetBangoUserId(_applicationId);
			setUserId();
			this.logProfile();
			
			setLocation();
		}
		catch (ex) {
			console.log(ex.message + ":" + ex.line);
		}
	};

	this.logEventToStore = function (eventName, eventValue, errorLevel, eventDetail, errorId, eventParameters) {

		var returnValue = -1;
		var eventTime = new Date();
		var eventLocalTime = new Date(eventTime.getTime() - (eventTime.getTimezoneOffset() * 60000));

		if (_logEvents) {
			returnValue = BangoStorage.logEvent(_useOfflineStorage, _connectionType, _operatorConnectionType, errorLevel, eventName, eventValue, eventDetail, errorId, eventTime, eventLocalTime, eventParameters);
			if (_maximumEventsPerProfile > 0 && returnValue >= _maximumEventsPerProfile) {
				this.logProfile();
				if (_postOnMaximumEvents == true) {
					this.postEventsNow(false, true);
				}
			}
		}
		return returnValue;
	};

	this.logProfile = function () {
		var profileId = BangoStorage.getCurrentProfileIdFromStore();
		if (profileId != 0) {
			var profile = BangoStorage.getProfile(profileId);
			_longitude = profile.LocationX;
			_latitude = profile.LocationY;
			_altitude = profile.LocationZ;
			_accuracy = profile.LocationAccuracy;
		}
		
		BangoStorage.logProfile(_useOfflineStorage, BangoConstants.SDK_TYPE(), BangoConstants.SDK_VERSION(), _applicationId, _applicationType, _applicationChannel, _applicationVersion,
								_userId, _bangoUserId, _sessionResumePeriod, _connectionType, _isRoaming, _locationSource, _altitude, _latitude, _longitude, _accuracy, _operatorCode, _operatorName, _countryISO, _operatorName, _deviceBrand, _deviceMake, _deviceModel, _product, _deviceVersion, _operatingSystem, _operatingSystemVersion, _operatorConnectionType);

		_profileLogged = true;

	};



	this.logEvent = function (eventName, eventValue, eventDetail, eventParameters) {
		return this.logEventToStore(eventName, eventValue, BangoConstants.ERROR_NONE(), eventDetail, "", eventParameters);
	};

	this.logEventStart = function (eventValue, eventDetail, eventParameters) {

		return this.logEvent(BangoSessionEvents.SESSION_START(), eventValue, eventDetail, eventParameters);
	};

	this.logEventError = function (errorId, message, errorClass, eventParameters) {
		return this.logEventToStore(BangoSessionEvents.EVENT_ERROR(), errorClass, BangoConstants.ERROR_USER(), message, errorId, eventParameters);
	};

	this.logInternalErrorCritical = function (ex) {
		return this.logInternalError(ex, BangoConstants.ERROR_INTERNAL_CRITICAL());
	};

	this.logInternalErrorWarning = function (ex) {
		return this.logInternalError(ex, BangoConstants.ERROR_INTERNAL_WARNING());
	};

	this.logInternalError = function (ex, errorLevel) {
		return this.logEventToStore("", errorLevel, ex.message, ex.sourceURL + ":" + ex.line, "", null);
	};

	function setLocation() {

		if (_findLocation) {
			try {
				// Set location then log the profile
				if (navigator.geolocation !== undefined) {
					navigator.geolocation.getCurrentPosition(foundLocation, noLocation);
				}
			}
			catch (ex) {
			}
		}
	}
	
	function setBangoUserId() {
		var profilePersistent = this.GetProfilePersistent(_useOfflineStorage);
		if (profilePersistent.length > 0) {
			var bangoUserId = profilePersistent.BangoUserId;
			BangoStorage.updateBangoUserId(_useOfflineStorage, bangoUserId);
		}
	}


	function foundLocation(position) {
		_latitude = position.coords.latitude;
		_longitude = position.coords.longitude;
		_altitude = position.coords.altitude;
		_accuracy = position.coords.accuracy;

		BangoStorage.updateLocation(_useOfflineStorage, _latitude, _longitude, _altitude, _accuracy);
	};


	function noLocation() {
		// if (console && console.log) console.log("Couldn't find a location");
	};


	function isWifi() {
		return (_connectionType == BangoConstants.WIFI_CONNECTION);
	};

	BangoStorage.initStorage(_useOfflineStorage);
}